Median of Two Sorted Arrays

There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays.
The overall run time complexity should be O(log (m+n)).

题目大意:给定2个已排序好的数组(大小分别为M和N),找出2个数组中所有数的中位数,时间复杂度 O(log(M+N))

题目难度:Hard

/**
 * Created by gzdaijie on 16/5/3
 * 新建一个数组(M+N),遍历2个数组进行排序,再取新数组的中位数
 * 因为给定数组是有序的,复杂度为O(M+N),居然能A
 * 当然有很多改进的地方,(1)遍历到总长度一半时停止,(2)不需要新建数组,2个临时变量,存下mid和mid-1
 * 但是仍改变不了复杂度是O(M+N)的事实
 */
public class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int len1 = nums1.length;
        int len2 = nums2.length;
        // 其中一个为空,返回另一个数组的中位数
        if (len1 == 0) return this.getMedian(nums2);
        if (len2 == 0) return this.getMedian(nums1);
        // t1和t2指针分别指向nums1和nums2,较小的值赋值给nums,指针前移
        int t1 = 0;
        int t2 = 0;
        int index = 0;
        int[] nums = new int[len1 + len2];
        while (t1 < len1 && t2 < len2) {
            if(nums1[t1] <= nums2[t2]) {
                nums[index++] = nums1[t1++];
            } else {
                nums[index++] = nums2[t2++];
            }
        }
        // 剩下部分继续赋值
        if (t1 == len1) {
            while (t2 < len2) {
                nums[index++] = nums2[t2++];
            }
        } else {
            while (t1 < len1) {
                nums[index++] = nums1[t1++];
            }
        }
        return this.getMedian(nums);
    }

    public double getMedian(int[] nums) {
        int flag = (nums.length + 1) % 2;
        int mid = nums.length / 2;
        return (nums[mid] + nums[mid - flag]) / 2.0;
    }
}
/**
 * Created by gzdaijie on 16/5/3.
 * 假设求第k大的数, 切2个有序数组,(Left1, Right1) (Left2, Right2), Left1.length + Left2.length == k
 * 记Left1的最大值为L1, Right1的最大值为R1, 那么如果L1 < R2 && L2 < R1, 那么第k大的数字就是 max(L1, L2)
 * 首先,nums1的切口在c1(c1初始值为k),nums2切口在k-c1, L1 > R2, c1需减小,L2 > R1, c1需增大
 * 切口位置可以使用二分法确定, 例如L1 > R2, c1需要减少,说明c1右边的切位都被排除,end = c1, 反之 start = c1
 * c1 = (start + end)/2
 * 复杂度 O(log(M+N))
 */
public class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int len1 = nums1.length;
        int len2 = nums2.length;
        int len = len1 + len2;
        // 一方为空,返回另一数组的中值
        if (len1 == 0) return this.getMedian(nums2);
        if (len2 == 0) return this.getMedian(nums1);

        // 确保len1小于len2,减少二分次数
        if (len1 > len2) {
            return findMedianSortedArrays(nums2, nums1);
        }
        // mid 中间位置, c1,c2记录切的位置, start,end用于二分确定切的位置
        int mid = len/2;
        int c1, c2;
        int start, end;
        int l1,l2,r1,r2;
        int MIN = Integer.MIN_VALUE;
        int MAX = Integer.MAX_VALUE;

        start = 0;
        end =  c1 = mid > len1 ? len1 : mid;
        c2 = mid - c1;

        while (true) {
            l1 = c1 == 0 ? MIN : nums1[c1 - 1];
            l2 = c2 == 0 ? MIN : nums2[c2 - 1];
            r1 = c1 == len1 ? MAX : nums1[c1];
            r2 = c2 == len2 ? MAX : nums2[c2];

            if (l1 <= r2 && l2 <= r1) {
                break;
            }
            if (l2 > r1) {
                start = c1;
            } else {
                end = c1;
            }
            c1 =  (start + end)/ 2;
            c2 = mid - c1;
        }

        if(len % 2 == 0) {
            return (Math.max(l1, l2) + Math.min(r1, r2)) / 2.0;
        } else {
            return Math.min(r1, r2) * 1.0;
        }

    }

    public double getMedian(int[] nums) {
        int flag = (nums.length + 1) % 2;
        int mid = nums.length / 2;
        return (nums[mid] + nums[mid - flag]) / 2.0;
    }
}

参考:leetCode讨论区

gzdaijie            updated 2016-05-03 17:48:26

results matching ""

    No results matching ""